package com.wenx.v3system.modular.platform.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wenx.v3dynamicdatasourcestarter.config.DynamicDataSourceConfig;
import com.wenx.v3system.modular.platform.domain.dto.PlatformRoleMenuDto;
import com.wenx.v3system.modular.platform.domain.po.PlatformRole;
import com.wenx.v3system.modular.platform.domain.po.PlatformRoleMenu;
import com.wenx.v3system.modular.platform.mapper.PlatformRoleMapper;
import com.wenx.v3system.modular.platform.mapper.PlatformRoleMenuMapper;
import com.wenx.v3system.modular.platform.service.PlatformRoleMenuService;
import com.wenx.v3system.modular.platform.service.PlatformRoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台角色菜单关联服务实现类
 * 使用lambda chain方式实现简化的菜单权限管理
 * 使用v3-platform数据源
 * 
 * @author wenx
 */
@Slf4j
@Service
@RequiredArgsConstructor
@DS(DynamicDataSourceConfig.PLATFORM_DATASOURCE)
public class PlatformRoleMenuServiceImpl extends ServiceImpl<PlatformRoleMenuMapper, PlatformRoleMenu> implements PlatformRoleMenuService {

    private final PlatformRoleService platformRoleService;
    private final PlatformRoleMapper platformRoleMapper;

    // 前端菜单配置映射 - 对应前端 PLATFORM_MENU_CONFIG
    private static final Map<String, Map<String, Object>> MENU_CONFIG = Map.of(
        "dashboard", Map.of("name", "平台概览", "path", "/platform/dashboard", "icon", "HomeOutlined", "order", 1),
        "tenant-management", Map.of("name", "租户管理", "path", "/platform/tenants", "icon", "ShopOutlined", "order", 2),
        "user-management", Map.of("name", "平台用户", "path", "/platform/users", "icon", "TeamOutlined", "order", 3),
        "role-management", Map.of("name", "角色管理", "path", "/platform/roles", "icon", "SafetyCertificateOutlined", "order", 4),
        "permission-management", Map.of("name", "权限管理", "path", "/platform/permissions", "icon", "KeyOutlined", "order", 5),
        "ticket-management", Map.of("name", "工单管理", "path", "/platform/tickets", "icon", "CustomerServiceOutlined", "order", 6),
        "profile", Map.of("name", "个人资料", "path", "/platform/profile", "icon", "UserOutlined", "order", 7),
        "settings", Map.of("name", "系统设置", "path", "/platform/settings", "icon", "SettingOutlined", "order", 8)
    );

    // 角色默认菜单配置
    private static final Map<String, List<String>> ROLE_DEFAULT_MENUS = Map.of(
        "super_admin", List.of("dashboard", "tenant-management", "user-management", "role-management", "permission-management", "ticket-management", "profile", "settings"),
        "platform_admin", List.of("dashboard", "tenant-management", "user-management", "role-management", "permission-management", "profile"),
        "platform_support", List.of("dashboard", "tenant-management", "ticket-management", "profile"),
        "platform_auditor", List.of("dashboard", "profile")
    );

    @Override
    public List<PlatformRoleMenuDto> getMenusByRoleCode(String roleCode) {
        // 优先返回内置角色的默认菜单
        List<String> defaultMenus = ROLE_DEFAULT_MENUS.get(roleCode);
        if (defaultMenus != null) {
            return defaultMenus.stream()
                    .map(this::createDtoFromMenuCode)
                    .collect(Collectors.toList());
        }

        // 查询自定义角色的菜单
        return this.list(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getRoleCode, roleCode)
                        .orderByAsc(PlatformRoleMenu::getSort)
        ).stream()
         .map(this::convertToDto)
         .collect(Collectors.toList());
    }

    @Override
    public List<String> getMenuCodesByRoleCode(String roleCode) {
        // 优先返回内置角色的默认菜单
        List<String> defaultMenus = ROLE_DEFAULT_MENUS.get(roleCode);
        if (defaultMenus != null) {
            return new ArrayList<>(defaultMenus);
        }

        // 查询自定义角色的菜单
        return this.list(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getRoleCode, roleCode)
                        .orderByAsc(PlatformRoleMenu::getSort)
        ).stream()
         .map(PlatformRoleMenu::getMenuCode)
         .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignMenusToRole(String roleCode, List<String> menuCodes) {
        // 删除原有关联
        this.remove(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getRoleCode, roleCode)
        );

        if (CollectionUtils.isEmpty(menuCodes)) {
            log.info("角色 {} 的菜单权限已清空", roleCode);
            return;
        }

        // 批量插入新关联
        List<PlatformRoleMenu> roleMenuList = menuCodes.stream()
                .map(menuCode -> createRoleMenu(roleCode, menuCode))
                .collect(Collectors.toList());

        this.saveBatch(roleMenuList);
        log.info("角色 {} 分配菜单权限成功，菜单数量: {}", roleCode, menuCodes.size());
    }

    @Override
    public List<String> getRoleCodesByMenuCode(String menuCode) {
        return this.list(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getMenuCode, menuCode)
        ).stream()
         .map(PlatformRoleMenu::getRoleCode)
         .distinct()
         .collect(Collectors.toList());
    }

    @Override
    public boolean hasMenu(String roleCode, String menuCode) {
        // 检查内置角色
        List<String> defaultMenus = ROLE_DEFAULT_MENUS.get(roleCode);
        if (defaultMenus != null) {
            return defaultMenus.contains(menuCode);
        }

        // 检查自定义角色
        return this.count(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getRoleCode, roleCode)
                        .eq(PlatformRoleMenu::getMenuCode, menuCode)
        ) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAllMenusByRoleCode(String roleCode) {
        this.remove(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getRoleCode, roleCode)
        );
        log.info("删除角色 {} 的所有菜单关联", roleCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAllRolesByMenuCode(String menuCode) {
        this.remove(
                new LambdaQueryWrapper<PlatformRoleMenu>()
                        .eq(PlatformRoleMenu::getMenuCode, menuCode)
        );
        log.info("删除菜单 {} 的所有角色关联", menuCode);
    }

    @Override
    public List<String> getUserMenuCodes(List<String> userRoleCodes) {
        if (CollectionUtils.isEmpty(userRoleCodes)) {
            return Collections.emptyList();
        }

        Set<String> menuCodes = new HashSet<>();

        userRoleCodes.forEach(roleCode -> {
            List<String> roleMenus = getMenuCodesByRoleCode(roleCode);
            menuCodes.addAll(roleMenus);
        });

        // 按菜单配置的顺序排序
        return menuCodes.stream()
                .sorted((m1, m2) -> {
                    Integer order1 = (Integer) MENU_CONFIG.getOrDefault(m1, Map.of("order", 999)).get("order");
                    Integer order2 = (Integer) MENU_CONFIG.getOrDefault(m2, Map.of("order", 999)).get("order");
                    return order1.compareTo(order2);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getMenuCodesByRoleId(Long roleId) {
        if (roleId == null) {
            return Collections.emptyList();
        }
        
        // 通过roleId获取角色实体
        PlatformRole role = platformRoleMapper.selectById(roleId);
        if (role == null) {
            log.warn("角色不存在，roleId: {}", roleId);
            return Collections.emptyList();
        }
        
        // 使用角色编码获取菜单权限
        return getMenuCodesByRoleCode(role.getCode());
    }

    /**
     * 创建角色菜单关联对象
     */
    private PlatformRoleMenu createRoleMenu(String roleCode, String menuCode) {
        PlatformRoleMenu roleMenu = new PlatformRoleMenu();
        roleMenu.setRoleCode(roleCode);
        roleMenu.setMenuCode(menuCode);
        
        // 从配置中获取菜单信息
        Map<String, Object> menuInfo = MENU_CONFIG.get(menuCode);
        if (menuInfo != null) {
            roleMenu.setMenuName((String) menuInfo.get("name"));
            roleMenu.setMenuPath((String) menuInfo.get("path"));
            roleMenu.setMenuIcon((String) menuInfo.get("icon"));
            roleMenu.setSort((Integer) menuInfo.get("order"));
        } else {
            roleMenu.setMenuName(menuCode);
            roleMenu.setSort(999);
        }
        
        return roleMenu;
    }

    /**
     * 从菜单编码创建DTO
     */
    private PlatformRoleMenuDto createDtoFromMenuCode(String menuCode) {
        PlatformRoleMenuDto dto = new PlatformRoleMenuDto();
        dto.setMenuCode(menuCode);
        
        // 从配置中获取菜单信息
        Map<String, Object> menuInfo = MENU_CONFIG.get(menuCode);
        if (menuInfo != null) {
            dto.setMenuName((String) menuInfo.get("name"));
            dto.setMenuPath((String) menuInfo.get("path"));
            dto.setMenuIcon((String) menuInfo.get("icon"));
            dto.setSort((Integer) menuInfo.get("order"));
        } else {
            dto.setMenuName(menuCode);
            dto.setSort(999);
        }
        
        dto.setStatus(1);
        return dto;
    }

    /**
     * 转换PO为DTO
     */
    private PlatformRoleMenuDto convertToDto(PlatformRoleMenu roleMenu) {
        PlatformRoleMenuDto dto = new PlatformRoleMenuDto();
        BeanUtils.copyProperties(roleMenu, dto);
        return dto;
    }
}